#python3.6.3


import time   #时间模块
from selenium import webdriver      #控制浏览器
#from selenium.webdriver.common.keys import Keys  #用于给元素赋值
from selenium.webdriver.support.select import Select  #控制下拉框模块
from selenium.webdriver.common.by import By   #寻找元素模块
from selenium.webdriver.support.ui import WebDriverWait  #“显示等待”模块
from selenium.webdriver.support import expected_conditions as EC  #等待条件模块
from asyncio.tasks import sleep
from func import login,monitorUntilPresent

#可以用input，也可以直接放入到后面的用户名、密码输入框中
#可以利用标准输入进行批量的操作，此处以个人抢票操作为例
username = str(input('请输入你的12306用户名：'))
password = str(input('请输入你的密码：'))  
#你12306账号中要购票的联系人的序号，4表示第五个
passenger = str(4)
#乘车日期
trainDate = '2018-02-01'
#硬座 1，硬卧 3，软卧 4，高级软卧 6，二等座 O（大写字母），一等座 M，商务座 9
#要抢的席别，按顺序
seatType = ['3','1']
#程序开始抢票的时间，非乘车时间！
start_time = "Thu Jan 09 17:31:00 2018"    
#监控的车次1，Z264次列车，不同车次需要得到相应的元素id替换这里
#trainNum1 = "ticket_630000Z26410"
trainNum1 = "ticket_630000K2260L"
#监控的车次1，Z230次列车
trainNum2 = "ticket_650000Z23002"
#始发站代号
stationFrom = "CZQ"
#目的站代号
stationTo = "LZJ"

print('数据初始化完成！')
print('-------------------------------------------------------')


b = time.mktime(time.strptime(start_time,"%a %b %d %H:%M:%S %Y"))        
print('计划抢票时间:' + time.strftime("%a %b %d %H:%M:%S %Y", time.localtime(b)) )  #此处是为了调试代码使用，可忽略，不影响使用
countDownSec = float(b)-time.time()    #利用自己设置的时间减去当前时间的时间戳
print('距离启动抢票还有:%f秒,本程序先睡一会儿...' % countDownSec)
#上一步骤得出的秒数就是需要等待抢票的时间
#此处倒计时已不用
time.sleep(1)    

#---------------------------------登录
print('本程序非常准时，已经醒来准备抢票啦!')
browser = webdriver.Firefox(executable_path="geckodriver")#驱动firefox浏览器
browser.get("https://kyfw.12306.cn/otn/login/init")#启动浏览器后进入该链接下
browser.find_element_by_id('username').clear()
#xxxxx更换为用户名  
browser.find_element_by_id('username').send_keys(username)
#xxxxx更换为密码   
browser.find_element_by_id('password').send_keys(password)
#此时的验证码需要人工识别并点击，该处设置10秒延迟，不够可以自行修改

#登录验证，需要完善，第一次验证码失败会有bug
login(browser)


#出发地点和到达地点设置WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "fromStation")))
time.sleep(2)
print('等待登录响应，先睡%d秒' % 2)
print('Waiting for login response HTML...当前时间毫秒: ' + str(time.time()))
#等待时间10秒，默认隔0.5秒查询一次
#yuding = WebDriverWait(browser,10).until(EC.presence_of_element_located((By.XPATH,'//li[@id="selectYuding"]/a' )))
yuding = WebDriverWait(browser,10).until(lambda x: x.find_element_by_xpath('//li[@id="selectYuding"]/a'))
yuding.click()
print('Login responsed！当前时间毫秒:'+ str(time.time()))


#-------------------------------------车票预定-查询
print('Before Click 车票预订')
#此处一般无需设置时间等待，调试代码时使用
#clickReserve = browser.find_element_by_link_text('车票预订').click()
clickReserve = browser.find_element_by_xpath('//li[@id="selectYuding"]/a').click()
time.sleep(5)
print('After Click 车票预订,Input StationFrom and StationTo...')
#出发地点和到达地点设置
#此处value值为出发时刻的地点，BJP表示北京，更改value值在页面上不加载，基本不耗时间，从页面中也看不到出发地和目的地
#此处内容以爬取，保存在stations.txt中，每行表示一个地址，打开文档ctrl + F查找即可
jsf = 'var a = document.getElementById("fromStation");a.value = "' + stationFrom +'"'
#此处将BJP更换为你需要的出发地址，value值在以爬取到stations.txt中，自行查看
#czx|郴州西|ICQ|chenzhouxi|czx|693@
#czh|郴州|CZQ|chenzhou|cz|121@
#lzh|兰州|LZJ|lanzhou|lz|51@
#lzx|兰州西|LAJ|lanzhouxi|lzx|52@
browser.execute_script(jsf)
jst = 'var a = document.getElementById("toStation");a.value = "' + stationTo +'"'
browser.execute_script(jst)
js = "document.getElementById('train_date').removeAttribute('readonly')"
browser.execute_script(js)
browser.find_element_by_id('train_date').clear()
browser.find_element_by_id('train_date').send_keys(trainDate)
#对于时间，我一直觉得网站计算的时间和自己获取的时间差一秒左右，这个根据不同环境自己测试start_time = "Thu Jan 04 10:00:00 2018"    
#首先设置需要抢票的时间b = time.mktime(time.strptime(start_time,"%a %b %d %H:%M:%S %Y"))
search = browser.find_element_by_id('query_ticket').click()
#此处是为了调试代码使用，可忽略，不影响使用a = float(b)-time.time()    
#利用自己设置的时间减去当前时间的时间戳time.sleep(a)    
#上一步骤得出的秒数就是需要等待抢票的时间browser.find_element_by_id('query_ticket').click()    
#时间到了先点击查询刷新一下，以防找不到元素

#-----------------------------------监控车票，提交订单
monitorUntilPresent(browser,trainNum1,trainNum2)

#normalPassenger_8 数字表示该账号下的第几位，默认从0开始如果是第一个则为normalPassenger_0
print('选择乘车人为: normalPassenger_' + passenger)
WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, 'normalPassenger_' + passenger)))
#id中的8表示账号下第九位print('a.value = "' + stationTo +'"')
browser.find_element_by_id('normalPassenger_' + passenger).click()

#此处value值看下方各个种类，6表示高级软卧
for st in seatType:
    try:
        s = Select(browser.find_element_by_id('seatType_' + st))
        print('选择席别:seatType_' + st)
        s.select_by_value(st)
        break
    except:
        print('Seat Type %s not exists.' % st)


#-------------------------准备提交订单
browser.find_element_by_id('submitOrder_id').click()
WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "qr_submit_id")))
print('点击 提交订单')
browser.find_element_by_link_text('提交订单').click()

#以下代码慎用，每天好像只有三次取消订单的机会，测试时可先注释掉
#【确认】提交订单，防止意外，这里以不同的方式查找元素并重复单击3次
sleep(3)
browser.find_element_by_id('qr_submit_id').click()
sleep(1)
browser.find_element_by_xpath('//*[@id="qr_submit_id"]').click()
sleep(1)
browser.find_element_by_link_text('确认').click()
print('已确认提交订单，请尽快付款！')




